package com.syf.starter.core.netty.handle;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

@Slf4j
@ChannelHandler.Sharable
public class IPCheckHandle extends ChannelInboundHandlerAdapter {
    /**
     * 黑名单ip通配符
     */
    private List<Pattern> blackIpPatterns = new ArrayList<>();

    /**
     * 白名单ip通配符
     */
    private List<Pattern> whiteIpPatterns = new ArrayList<>();

    public IPCheckHandle(List<String> blackIpPatterns, List<String> whiteIpPatterns) {
        super();
        if (blackIpPatterns != null) {
            for (String blackIpPattern : blackIpPatterns) {
                this.blackIpPatterns.add(Pattern.compile(blackIpPattern));
            }
        }

        if (whiteIpPatterns != null) {
            for (String whiteIpPattern : whiteIpPatterns) {
                this.whiteIpPatterns.add(Pattern.compile(whiteIpPattern));
            }
        }
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        InetSocketAddress clientAddr = (InetSocketAddress) ctx.channel().remoteAddress();
        String clientIp = clientAddr.getHostString();

        if (isBlackIp(clientIp)) {
            log.error("设置了黑名单，clientIp:[{}]在黑名单内，非法交易!", clientIp);
            ReferenceCountUtil.release(msg);
            ctx.channel().close();
            return;
        }

        if (!isWhiteIp(clientIp)) {
            log.error("设置了白名单，但clientIp:[{}]不在白名单内，非法交易!", clientIp);
            ReferenceCountUtil.release(msg);
            ctx.channel().close();
            return;
        }

        ctx.fireChannelRead(msg);
    }

    private boolean isWhiteIp(String clientIp) {
        if (whiteIpPatterns.size() == 0) {
            return true;
        }

        for (Pattern whiteIpPattern : whiteIpPatterns) {
            if (whiteIpPattern.matcher(clientIp).matches()) {
                return true;
            }
        }

        return false;
    }

    private boolean isBlackIp(String clientIp) {
        for (Pattern blackIpPattern : blackIpPatterns) {
            if (blackIpPattern.matcher(clientIp).matches()) {
                return true;
            }
        }

        return false;
    }
}
